package script2
{
	/**
	 * 词法分析器
	 * @author blank
	 * 
	 */
	public class Lex
	{
		/**
		 * 源代码
		 */
		private var _text:String;
		
		/**
		 * 被解析的词法标识符列表
		 */
		private var _words:Vector.<Token>;
		
		/**
		 * 行列表
		 */
		private var lines:Vector.<String>;
		
		/**
		 * 当前行
		 */
		private var curLineIndex:int;
		
		/**
		 * 当前字符索引
		 */
		private var curChIndex:int;
		
		/**
		 * 当前字符
		 */
		private var ch:String;
		
		/**
		 * 转换错误信息
		 * @param message
		 * 
		 */
		private function parseError( message:String ):void {
			throw new Error(lines[curLineIndex] + " 词法分析出错: " + message + " 当前位置=" + curChIndex);
		}
		
		/**
		 * 统一换行符
		 * @param text
		 * 
		 */
		private function replaceNewline(text:String):void{
			text=text.replace(/\r\n/g,"\n");
			text=text.replace(/\r/g,"\n");
		}
		
		/**
		 * 指向下一个字符
		 * @return 
		 * 
		 */
		private function nextChar():String{
			ch=_text.charAt(curChIndex++);
			return ch;
		}
		
		/**
		 * 是否为空白字符
		 * @param ch
		 * @return 
		 * 
		 */
		private function isWhiteSpace(ch:String):Boolean {
			return (ch==' ' || ch == '　' || ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n');
		}
		
		/**
		 * 是否为数字
		 * @param ch
		 * @return 
		 * 
		 */
		private function isDigit(ch:String):Boolean {
			return (ch > 47 && ch < 58);//0-9,48-57
		}
		
		/**
		 * 是否为字母
		 * @param c
		 * @return 
		 * 
		 */
		private function isAlpha(ch:String):Boolean{
			const CODE:Number=ch.charCodeAt(0);
			
			if(CODE < 127){
				if(
					(CODE < 91 && CODE > 64) //小写字母
					|| 
					(CODE > 96 && CODE < 123) //大写字母
					|| 
					CODE == 95 //下划线
				){
					return true;
				}
			}else{
				if(CODE >= 0x4e00 && CODE <= 0x9fa5){ //汉字的unicode编码范围
					return true;
				}
			}
			return false;
		}
		
		/**
		 * 跳过空白字符
		 * 
		 */
		private function skipWhite():void {
			while(isWhiteSpace(ch)){
				if(ch=='\n'){
					curLineIndex++;
				}
				nextChar();
			}
		}
		
		/**
		 * 跳过注释
		 * @return 
		 * 
		 */
		private function skipComments():void{
			while(ch == '/') {
				nextChar();
				switch(ch) {
					case "/"://行注释
						do{
							nextChar();
						}while(ch != "\n");
						break;
					case "*"://块注释
						nextChar();
						while ( true ) {
							if ( ch == '*' ) {
								nextChar();
								if ( ch == '/') {
									nextChar();
									break;
								}
							} else {
								if(ch=="\n"){
									curLineIndex++;
								}
								nextChar();
							}
							
							//到文本结尾了
							if ( ch == '' ) {
								parseError( "多行注释未找到结束符(\"*/\")" );
							}
						}
						break;
					default://不是注释回到起点
						curChIndex -= 2;
						nextChar();
						break;
				}
			}
		}
		
		/**
		 * 跳过需要忽略的内容
		 * 
		 */
		private function skipIgnored():void {
			skipWhite();
			var n:int=0;
			while(skipComments() && n<40){
				n++;
				skipWhite();
			}
		}
		
		/**
		 * 获取下一个单词
		 * @return 
		 * 
		 */
		private function getNextWord():Token{
			skipIgnored();
			
			var token:Token=new Token();
			
			switch(ch){
				case '{':
					token.type = Token.L_BRACE;
					token.word = '{';
					token.value=token.word;
					nextChar();
					break
				
				case '}':
					token.type = Token.R_BRACE;
					token.word = '}';
					token.value=token.word;
					nextChar();
					break
				
				case '(':
					token.type = Token.L_PARENT;
					token.word= '(';
					token.value=token.word;
					nextChar();
					break
				
				case ')':
					token.type = Token.R_PARENT;
					token.word= ')';
					token.value=token.word;
					nextChar();
					break
				
				case '.':
					token.type = Token.DOT;
					token.word = '.';
					token.value=token.word;
					nextChar();
					break
				
				case ';':
					token.type = Token.SEMICOLON;
					token.word = ';';
					token.value=token.word;
					nextChar();
					break
				
				case ',':
					token.type = Token.COMMA;
					token.word = ',';
					token.value=token.word;
					nextChar();
					break;
			}
			
			return null;
		}
		
		/**
		 * 词法分析器
		 * @param text
		 * 
		 */
		public function Lex(text:String){
			_text=text;
			
			if(text){
				_words=new Vector.<Token>();
				
				lines=Vector.<String>(text.split("\n"));
				curLineIndex=0;
				
				nextChar();
				
				const LEN:int=_text.length;
				
				var tk:Token;
				while(curChIndex <= LEN){
					try{
						tk=getNextWord();
						
						tk.lineIndex=curLineIndex;
						tk.lineText=lines[curLineIndex];
					}catch(e:Error){
						
					}
					
					if(tk){
						_words.push(tk);
					}
				}
			}
		}
	}
}